package com.magnificent.panda.ui.dialog;

import com.magnificent.graph.model.Cell;
import com.magnificent.panda.correlation.*;
import com.magnificent.panda.model.entity.FlowEvent;
import com.magnificent.panda.resources.Resources;
import com.magnificent.panda.utils.JFreeChartHelper;
import com.magnificent.panda.utils.PandaConstants;
import com.silverhaze.commons.helpers.CommonUIHelper;
import com.silverhaze.commons.helpers.UI;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.xy.XYDataset;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

/**
 * User: Babanin
 * Date: 13.03.2010
 * Time: 0:25:21
 */
public class CorrelationSettingsDialog extends JDialog {

    private static int countCorrelation = 5;
    private static int discreteInterval = 10;

    private Cell functionCell;
    private Cell mainCellActor;
    private List<Cell> slaveCellActors;

    private JButton countButton;
    private JCheckBox useConnectionsCheckBox;
    private JSpinner discreteIntervalSpinner;
    private JSpinner countCorrelationSpinner;
    private JComboBox correlationFunctionComboBox;

    private JFreeChart correlationChart;
    private ChartPanel correlationChartPanel;

    private IntervalCorrelationFunction intervalCorrelationFunction;

    private JLabel moduleLabel;

    public CorrelationSettingsDialog(Cell mainCellActor, List<Cell> slaveCellActors, Cell functionCell) {
        this.mainCellActor = mainCellActor;
        this.slaveCellActors = slaveCellActors;
        this.functionCell = functionCell;

        initializeControls();
        initializeView();
    }

    private void initializeView() {
        setLayout(new BorderLayout());
        setIconImage(Resources.APP_ICON.getImage());
        getRootPane().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        setTitle(PandaConstants.PANDA_TITLE + " - Моделирование");

        add(CommonUIHelper.createBorderLayoutPanel(
                new JComponent[]{
                        CommonUIHelper.createHorizontalBox(
                                "ИКФ: ", correlationFunctionComboBox, 10, "Дискретизация: ", discreteIntervalSpinner, 10,
                                "Отсчётов: ", countCorrelationSpinner
                        ),
                        UI.hBox(useConnectionsCheckBox, 10, countButton)
                },
                new Object[]{
                        BorderLayout.LINE_START,
                        BorderLayout.LINE_END
                }
        ), BorderLayout.NORTH);


        add(CommonUIHelper.packInShiftedPanel(correlationChartPanel, 5, 5, 0, 0), BorderLayout.CENTER);

        add(
                CommonUIHelper.createBorderLayoutPanel(new JComponent[]{
                        CommonUIHelper.hBox(
                                "Модуль ИКФ: ", moduleLabel
                        ),
                        new JButton(new AbstractAction("Закрыть") {
                            public void actionPerformed(ActionEvent e) {
                                CorrelationSettingsDialog.this.dispose();
                            }
                        })
                }, new Object[]{
                        BorderLayout.LINE_START, BorderLayout.LINE_END
                }), BorderLayout.SOUTH);

        pack();
        setLocationRelativeTo(null);
    }

    private void initializeControls() {
        intervalCorrelationFunction = new ProhorovCorrelationFunction();

        moduleLabel = new JLabel("");

        useConnectionsCheckBox = new JCheckBox("учитывать связи");
        countButton = new JButton(new AbstractAction("Расчитать") {
            public void actionPerformed(ActionEvent e) {
                List<FlowEvent> mainEvents = mainCellActor.getFlowActor().getEvents();

                FlowEvent[] masterValues = new FlowEvent[mainEvents.size()];
                FlowEvent[][] secondFlowDoubles = new FlowEvent[slaveCellActors.size()][];

                int i = 0;
                for (FlowEvent firstFlowValue : mainEvents) {
                    masterValues[i++] = firstFlowValue;
                }

                i = 0;
                for (Cell slaveCell : slaveCellActors) {
                    List<FlowEvent> slaveEvents = slaveCell.getFlowActor().getEvents();
                    int j = 0;
                    secondFlowDoubles[i] = new FlowEvent[slaveEvents.size()];
                    for (FlowEvent slaveEvent : slaveEvents) {
                        secondFlowDoubles[i][j++] = slaveEvent;
                    }
                    i++;
                }

                countCorrelation = (Integer) countCorrelationSpinner.getValue();
                discreteInterval = (Integer) discreteIntervalSpinner.getValue();

                if (secondFlowDoubles.length == 1) {
                    double[] correlation = intervalCorrelationFunction.calculateCorrelation(masterValues, secondFlowDoubles[0],
                            countCorrelation, discreteInterval);

                    double[] correlationMixed = intervalCorrelationFunction.calculateCorrelation(masterValues, secondFlowDoubles[0],
                            countCorrelation, discreteInterval);

                    double moduleValue = CorrelationHelper.countModule(correlation);
                    moduleLabel.setText("" + PandaConstants.DOUBLE_FORMAT.format(moduleValue));

                    updateGraph(correlation, correlationMixed);
                } else {
                    intervalCorrelationFunction = new IvashenkoFlowsCorrelationFunction();
                    double[] correlation = intervalCorrelationFunction.calculateCorrelation(masterValues, secondFlowDoubles,
                            countCorrelation, discreteInterval, useConnectionsCheckBox.isSelected());

                    updateGraph(correlation, new double[0]);
                }
            }
        });
        discreteIntervalSpinner = new JSpinner(new SpinnerNumberModel(discreteInterval, 1, 100, 1));
        countCorrelationSpinner = new JSpinner(new SpinnerNumberModel(countCorrelation, 1, 1000, 1));

        correlationChart = JFreeChartHelper.newCorrelationChart(JFreeChartHelper.createFlowDataset(new ArrayList<FlowEvent>()), "", "", "");

        correlationChartPanel = new ChartPanel(correlationChart);
        correlationChartPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK));

        if (slaveCellActors.size() == 1) {
            correlationFunctionComboBox = new JComboBox(new IntervalCorrelationFunction[]{
                    new ProhorovCorrelationFunction(),
                    new IvashenkoCorrelationFunction(),
                    new IvashenkoImprovedCorrelationFunction()
            });
        } else {
            correlationFunctionComboBox = new JComboBox(new IntervalCorrelationFunction[]{
                    new IvashenkoFlowsCorrelationFunction()
            });
        }
    }

    private void updateGraph(double[] correlation, double[] correlationMixed) {
        XYDataset dataset = JFreeChartHelper.createDataset(correlation, correlationMixed);

        correlationChart.getXYPlot().setDataset(0, dataset);
    }

    public static void show(Cell mainActor, List<Cell> slaveActors, Cell function) {
        CorrelationSettingsDialog dialog = new CorrelationSettingsDialog(mainActor, slaveActors, function);
        dialog.setVisible(true);
    }
}